package com.example.netty.netty.codec;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.protobuf.ProtobufDecoder;

public class NettyServer {
    public static void main(String[] args) throws Exception{
        //创建Group
        //说明：1、NioEventLoopGroup默认有cpu核数*2个子线程即NioEventLoop
        //      2、线程数也可以手动指定 new NioEventLoopGroup(1)
        //      3、各个线程之间的负载均衡策略是轮询
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            //创建一个服务器对象，用于设置参数
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            serverBootstrap.group(bossGroup, workerGroup)    //设置两个group
                    .channel(NioServerSocketChannel.class)  //设置服务器bossGroup使用的通道
                    .option(ChannelOption.SO_BACKLOG, 128)  //设置bossGroup线程队列最大连接个数
                    .childOption(ChannelOption.SO_KEEPALIVE, true)   //设置workerGroup是否保持活动连接状态
                    //设置workerGroup通道初始化对象（匿名对象）
                    .childHandler(new ChannelInitializer<SocketChannel>() { //通道类型，netty包中的
                        //给pipline中设置处理器
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            socketChannel.pipeline()
                                    //加入解码器，指定对象类型
                                    .addLast(new ProtobufDecoder(StudentPOJO.Student.getDefaultInstance()))
                                    .addLast(new NettyServerHandler());
                        }
                    });
            ChannelFuture channelFuture = serverBootstrap.bind(6668).sync();

            //添加自定义监听器
            channelFuture.addListener(new ChannelFutureListener() {
                @Override
                public void operationComplete(ChannelFuture channelFuture) throws Exception {
                    if (channelFuture.isSuccess()) {
                        System.out.println("服务器启动成功。。。。。");
                    }
                }
            });

            //监听对通道的关闭
            channelFuture.channel().closeFuture().sync();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //出现异常后优雅关闭group
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}
